﻿namespace JunFan.Repositories
{
    using System;
    using System.Collections.Generic;
    using AutoMapper;

    public abstract class RepositoryBase<TDomain, TDto> : IRepository<TDomain>
    {
        #region IRepository

        public abstract TDomain Create(TDomain item);
        public abstract TDomain Read(int id);
        public abstract IEnumerable<TDomain> ReadAll();
        public abstract IEnumerable<TDomain> ReadAll(Func<TDomain, bool> filter);
        public abstract void Update(TDomain item);
        public abstract bool Exists(TDomain item);

        #endregion IRepository

        #region OnContext

        protected T OnContext<T>(Func<EfContext, T> action)
        {
            using (var context = new EfContext())
            {
                return action(context);
            }
        }

        protected void OnContext(Action<EfContext> action)
        {
            using (var context = new EfContext())
            {
                action(context);
            }
        }

        #endregion OnContext

        #region Mapping

        protected static TDomain MapToDomain(TDto dto)
        {
            return Mapper.Map<TDomain>(dto);
        }

        protected IEnumerable<TDomain> MapToDomain(List<TDto> dtos)
        {
            return Mapper.Map<List<TDto>, List<TDomain>>(dtos);
        }

        protected static TDto MapToDto(TDomain item)
        {
            return Mapper.Map<TDto>(item);
        }

        protected Func<TDto, bool> MapPredicate(Func<TDomain, bool> predicate)
        {
            Func<TDto, TDomain> mappingFunc = Mapper.CreateMapExpression<TDto, TDomain>().Compile();
            return x => predicate(mappingFunc(x));
        }

        #endregion Mapping
    }
}